﻿/*
 * @author: wizardc
 */

using Dou.Clip;
using Dou.GPU;
using Dou.Job;
using Unity.Burst;
using Unity.Collections.LowLevel.Unsafe;

namespace Demo.WorldMap.GPU
{
    /// <summary>
    /// 填充当前绘制批次的数据，因为涉及到数据添加所以不能并行处理，具体会进行下面的处理：
    /// 
    /// 1. 根据资源显示信息和当前的LOD，取出所有最终会进行绘制的Mesh材质对；
    /// 2. 对每个对象进行视椎剔除的检测；
    /// 
    /// 更新逻辑：
    /// 1. 强制更新的情况，清除所有缓冲重新添加（对应LOD切换时等情况）
    /// 2. 非强制更新的情况，仅更新出现变动的缓冲（对应仅屏幕拖动时的情况）
    /// </summary>
    [BurstCompile]
    public unsafe class FillBatchDataJob : ManagedJob<FillBatchDataJob>.IWork
    {
        public SceneStaticCameraCtl cameraCtl;
        public GPUDrawContainer _container;

        [BurstCompile]
        [Il2CppSetOption(Option.ArrayBoundsChecks, false)]
        [Il2CppSetOption(Option.NullChecks, false)]
        public void Execute()
        {
            var resCount = _container.resCount;
            for (int i = 0; i < resCount; i++)
            {
                var resInfo = _container.GetResInfo(i);

                // 有数据时才进行判断和填充
                if (resInfo.dataLen > 0)
                {
                    var transCount = resInfo.dataLen / GPUDefine.Stride_Float4x4;
                    var transPtr = resInfo.transData.GetUnsafePtr();

                    // 仅填充当前LOD下存在的资源
                    var lodIds = resInfo.GetLodIds();
                    var lodIdCount = lodIds.Length;
                    for (int j = 0; j < lodIdCount; j++)
                    {
                        var batchDraw = _container.GetBatchDraw(lodIds[j]);
                        // 加载资源
                        batchDraw.LoadResIfNeed();
                        // 处理每个对象
                        for (int k = 0; k < transCount; k++)
                        {
                            // 判定是否可视
                            var ptr = transPtr + k * GPUDefine.Stride_Float4x4;
                            var clipping = cameraCtl.GetClipping((float*) ptr);
                            if (clipping == FrustumClippingType.Cross || clipping == FrustumClippingType.Inner)
                            {
                                batchDraw.AddTransform(ptr, GPUDefine.Stride_Float4x4);
                            }
                        }
                    }
                }
            }
        }
    }
}
